﻿using Newtonsoft.Json;
using SharpCompress.Common;
using System.Net;
using System.Text;
using 请求响应加密.Common;
using 请求响应加密.Tools.Config;

namespace 请求响应加密.Tools.Http
{
    public class HttpHelper
    {
        /// <summary>
        /// 配置并返回一个 HttpClient 实例
        /// </summary>
        /// <param name="customHeaders">自定义请求头</param>
        /// <param name="proxySetting">代理设置</param>
        /// <param name="url">请求的 URL</param>
        /// <returns>配置好的 HttpClient 实例</returns>      
        public static HttpClient HttpClientSettings(Dictionary<string, string> customHeaders, ProxySetting proxySetting)
        {
            // 创建 HttpClientHandler 并禁用自动解压缩
            var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip };

            if (proxySetting != null && proxySetting.UseProxy)
            {
                // 在日志里记录是否使用代理，方便排查问题
                LogHelper.Info(string.Format("UseProxy is [{0}]", proxySetting.UseProxy));

                // 构建代理 URL
                string proxyUrl = string.Format("{0}://{1}:{2}", proxySetting.Protocol, proxySetting.Address, proxySetting.Port);
                LogHelper.Info(string.Format("Proxy url is [{0}]", proxyUrl));

                // 创建 Web 代理对象
                IWebProxy webProxy = new WebProxy(proxyUrl);
                if (proxySetting.ProxyCredentials != null && !string.IsNullOrEmpty(proxySetting.ProxyCredentials.UserName) && !string.IsNullOrEmpty(proxySetting.ProxyCredentials.Password))
                {
                    LogHelper.Info(string.Format("ProxyCredentials.UserName is [{0}]", proxySetting.ProxyCredentials.UserName));

                    // 设置代码身份信息
                    webProxy.Credentials = new NetworkCredential(proxySetting.ProxyCredentials.UserName, proxySetting.ProxyCredentials.Password);
                }
                handler.Proxy = webProxy; // 设置 HttpClientHandler 的代理
                handler.UseProxy = true; // 启用代理
            }

            // 创建 HttpClient 实例
            HttpClient httpclient = new HttpClient(handler);

            // 添加自定义请求头
            if (customHeaders != null)
            {
                var headerInfo = JsonConvert.SerializeObject(customHeaders);
                LogHelper.Info(string.Format("Custom header info: [{0}]", headerInfo));
                foreach (KeyValuePair<string, string> headerItem in customHeaders)
                {
                    if (!string.IsNullOrEmpty(headerItem.Value))
                    {
                        httpclient.DefaultRequestHeaders.Add(headerItem.Key, headerItem.Value.Trim());
                    }
                }
            }
            // 配置响应超时时间
            int timeout = ConfigHelper.Get<int>("HttpConfig", "RespTimeout") == 0 ? 30 : ConfigHelper.Get<int>("HttpConfig", "RespTimeout");
            httpclient.Timeout = TimeSpan.FromSeconds(timeout);

            // 返回配置好的 HttpClient 实例
            return httpclient;
        }

        /// <summary>
        /// 默认信任证书，忽略证书警告。
        /// </summary>
        private static void trustCertificate()
        {
            //默认忽略证书
            ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
            //兼容所有ssl协议
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
        }

        /// <summary>
        /// 根据 URL 判断 HTTP 模式（HTTP 或 HTTPS）。
        /// </summary>
        /// <param name="url">请求的 URL</param>
        /// <returns>HTTP 模式</returns>
        private static HttpMode GetHttpModeByUrl(string url)
        {
            HttpMode httpMode = HttpMode.HTTP;
            if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                httpMode = HttpMode.HTTPS;
            }
            return httpMode;
        }

        /// <summary>
        /// 同步方式发送 HTTP 请求并返回响应字符串。
        /// </summary>
        /// <param name="url">请求的 URL</param>
        /// <param name="paramlist">请求参数</param>
        /// <param name="customHeaders">自定义请求头</param>
        /// <param name="proxySetting">代理设置</param>
        /// <param name="httpMethodType">HTTP 方法类型</param>
        /// <returns>响应字符串</returns>
        public static string HttpclientCall(string url, HttpContent paramlist, Dictionary<string, string> customHeaders, ProxySetting proxySetting, HttpMethodType httpMethodType)
        {
            // 获取请求的 HTTP 模式（HTTP 或 HTTPS）
            HttpMode httpMode = GetHttpModeByUrl(url);
            if (httpMode == HttpMode.HTTPS)
            {
                trustCertificate(); //如果是 HTTPS，忽略证书警告
            }

            HttpClient httpclient = null;
            Stream ResponseStream = null;
            StreamReader sr = null;
            HttpResponseMessage response = null;
            try
            {
                // 配置 HttpClient 实例
                httpclient = HttpClientSettings(customHeaders, proxySetting);
                CompressedContent content = null;
                if (paramlist != null)
                {
                    // 压缩请求内容
                    content = new CompressedContent(paramlist, CompressionType.GZip);
                }
                string retString = string.Empty;

                LogHelper.Info(string.Format("Call Url=[{0}], Method=[{1}]", url, httpMethodType.ToString()));

                switch (httpMethodType)
                {
                    case HttpMethodType.GET:
                        response = httpclient.GetAsync(new Uri(url)).Result;
                        break;
                    case HttpMethodType.POST:
                        response = httpclient.PostAsync(new Uri(url), content).Result;
                        break;
                    case HttpMethodType.PUT:
                        response = httpclient.PutAsync(new Uri(url), content).Result;
                        break;
                    case HttpMethodType.DELETE:
                        response = httpclient.DeleteAsync(new Uri(url)).Result;
                        break;
                    default:
                        throw new NotSupportedException("This type is not supported!");
                }

                // 确保响应状态码为成功
                response.EnsureSuccessStatusCode();

                // 获取响应流
                ResponseStream = response.Content.ReadAsStreamAsync().Result;
                sr = new StreamReader(ResponseStream, Encoding.GetEncoding("utf-8"));
                retString = sr.ReadToEnd();

                return retString;
            }
            catch (Exception ex)
            {
                LogHelper.Error("请求调用失败", ex);
            }
            finally
            {
                // 依次释放资源
                if (response != null) response.Dispose();
                if (sr != null) sr.Close();
                if (ResponseStream != null) ResponseStream.Close();
                if (httpclient != null) httpclient.Dispose();
            }
            return "";
        }

        /// <summary>
        /// 异步发送 HTTP 请求并返回响应字符串。
        /// </summary>
        public async Task<string> HttpclientCallAsync(string url, HttpContent paramlist, Dictionary<string, string> customHeaders, ProxySetting proxySetting, HttpMethodType httpMethodType)
        {
            // 获取请求的 HTTP 模式（HTTP 或 HTTPS）
            HttpMode httpMode = GetHttpModeByUrl(url);
            if (httpMode == HttpMode.HTTPS)
            {
                trustCertificate(); //如果是 HTTPS，忽略证书警告
            }

            HttpClient httpclient = null;
            Stream ResponseStream = null;
            StreamReader sr = null;
            HttpResponseMessage response = null;
            try
            {
                httpclient = HttpClientSettings(customHeaders, proxySetting);
                CompressedContent content = null;
                if (paramlist != null)
                {
                    content = new CompressedContent(paramlist, CompressionType.GZip);
                }
                string retString = string.Empty;

                LogHelper.Info(string.Format("Call Url=[{0}], Method=[{1}]", url, httpMethodType.ToString()));

                switch (httpMethodType)
                {
                    case HttpMethodType.GET:
                        response = await httpclient.GetAsync(new Uri(url));
                        break;
                    case HttpMethodType.POST:
                        response = await httpclient.PostAsync(new Uri(url), content);
                        break;
                    case HttpMethodType.PUT:
                        response = await httpclient.PutAsync(new Uri(url), content);
                        break;
                    case HttpMethodType.DELETE:
                        response = await httpclient.DeleteAsync(new Uri(url));
                        break;
                    default:
                        throw new NotSupportedException("This type is not supported!");
                }

                response.EnsureSuccessStatusCode();
                ResponseStream = await response.Content.ReadAsStreamAsync();
                sr = new StreamReader(ResponseStream, Encoding.GetEncoding("utf-8"));
                retString = sr.ReadToEnd();

                return retString;
            }
            catch (Exception ex)
            {
                LogHelper.Error("请求调用失败", ex);
            }
            finally
            {
                if (response != null) response.Dispose();
                if (sr != null) sr.Close();
                if (ResponseStream != null) ResponseStream.Close();
                if (httpclient != null) httpclient.Dispose();
            }
            return "";
        }
    }
    public enum HttpMode
    {
        HTTP,
        HTTPS
    }

    public enum HttpMethodType
    {
        GET, POST, PUT, DELETE
    }
}
